/*-CREATE SERVER-*/
const express = require('express'),
    app = express(),
    bodyParser = require('body-parser'),
    fs = require('fs'),
    SparkMD5 = require('spark-md5'),
    PORT = 8888;
const path = require('path'); // 导入 path 模块
const mime = require('mime-types');  // 需要安装 mime-types 库来自动获取文件的 MIME 类型
const crypto = require('crypto');
//配置下载路径
app.use('/upload', express.static(path.join(__dirname, 'upload')));

app.listen(PORT, () => {
    console.log(`THE WEB SERVICE IS CREATED SUCCESSFULLY AND IS LISTENING TO THE PORT：${PORT}`);
});
app.use(bodyParser.urlencoded({
    extended: false,
    limit: '1024mb'
}));

/*-API-*/
const multiparty = require("multiparty"),
    uploadDir = `${__dirname}/upload`;

function handleMultiparty(req, res, temp) {
    return new Promise((resolve, reject) => {
        // multiparty的配置
        let options = {
            maxFieldsSize: 200 * 1024 * 1024
        };
        !temp ? options.uploadDir = uploadDir : null;
        let form = new multiparty.Form(options);
        // multiparty解析
        form.parse(req, function (err, fields, files) {
            if (err) {
                res.send({
                    code: 1,
                    reason: err
                });
                reject(err);
                return;
            }
            resolve({
                fields,
                files
            });
        });
    });
}

app.get('/download/:filename', (req, res) => {
    const filename = req.params.filename;
    const filePath = path.join(__dirname, 'upload', filename);

    // 检查文件是否存在
    if (!fs.existsSync(filePath)) {
        return res.status(404).json({
            code: 404,
            message: 'File not found',
            data: null
        });
    }

    // 获取文件的 MIME 类型（根据文件扩展名）
    // mime.lookup(filename) || 
    const mimeType = mime.lookup(filename) || 'application/octet-stream';  // 默认值是二进制流

    // 获取文件大小
    const stats = fs.statSync(filePath);
    const fileSize = stats.size;

    // 设置响应头   
    res.setHeader('Content-Disposition', `inline; filename="${filename}"`);  // 修改为 inline，支持预览
    res.setHeader('Content-Type', mimeType);  // 根据文件类型动态设置
    res.setHeader('Content-Length', fileSize); // 设置准确的文件大小

    // 发送文件
    res.sendFile(filePath, (err) => {
        if (err) {
            return res.status(500).json({
                code: 500,
                message: 'File download failed',
                data: null
            });
        }
    });
});

// 基于FORM-DATA上传数据
app.post('/single1', async (req, res) => {
    let {
        files
    } = await handleMultiparty(req, res);
    let file = files.file[0];
    res.send({
        code: 0,
        originalFilename: file.originalFilename,
        path: file.path.replace(__dirname, `http://127.0.0.1:${PORT}`)
    });
});

// 上传BASE64
app.post('/single2', (req, res) => {
    let {
        chunk,
        filename
    } = req.body;

    // chunk的处理：转换为buffer
    chunk = decodeURIComponent(chunk);
    chunk = chunk.replace(/^data:image\/\w+;base64,/, "");
    chunk = Buffer.from(chunk, 'base64');

    // 存储文件到服务器
    let spark = new SparkMD5.ArrayBuffer(),
        suffix = /\.([0-9a-zA-Z]+)$/.exec(filename)[1],
        path;
    spark.append(chunk);
    path = `${uploadDir}/${spark.end()}.${suffix}`;
    fs.writeFileSync(path, chunk);
    res.send({
        code: 0,
        originalFilename: filename,
        path: path.replace(__dirname, `http://127.0.0.1:${PORT}`)
    });
});

// // 切片上传 && 合并
// app.post('/single3', async (req, res) => {
//     let {
//         fields,
//         files
//     } = await handleMultiparty(req, res, true);
//     console.log(1);

//     let [chunk] = files.chunk,
//         [filename] = fields.filename;
//     let hash = /([0-9a-zA-Z]+)_\d+/.exec(filename)[1],
//         // suffix = /\.([0-9a-zA-Z]+)$/.exec(file.name)[1],
//         path = `${uploadDir}/${hash}`;
//     !fs.existsSync(path) ? fs.mkdirSync(path) : null;
//     path = `${path}/${filename}`;
//     fs.access(path, async err => {
//         // 存在的则不再进行任何的处理
//         if (!err) {
//             res.send({
//                 code: 0,
//                 path: path.replace(__dirname, `http://127.0.0.1:${PORT}`)
//             });
//             return;
//         }

//         // // 为了测试出效果，延迟1秒钟
//         // await new Promise(resolve => {
//         //     setTimeout(_ => {
//         //         resolve();
//         //     }, 200);
//         // });

//         // 不存在的再创建
//         let readStream = fs.createReadStream(chunk.path),
//             writeStream = fs.createWriteStream(path);
//         readStream.pipe(writeStream);
//         readStream.on('end', function () {
//             fs.unlinkSync(chunk.path);
//             res.send({
//                 code: 0,
//                 path: path.replace(__dirname, `http://127.0.0.1:${PORT}`)
//             });
//         });
//     });
// });

// app.get('/merge', (req, res) => {
//     let {
//         hash,
//         fileName
//     } = req.query;

//     let path = `${uploadDir}/${hash}`,
//         fileList = fs.readdirSync(path),
//         suffix;
//     fileList.sort((a, b) => {
//         let reg = /_(\d+)/;
//         return reg.exec(a)[1] - reg.exec(b)[1];
//     }).forEach(item => {
//         !suffix ? suffix = /\.([0-9a-zA-Z]+)$/.exec(item)[1] : null;
//         fs.appendFileSync(`${uploadDir}/${hash}.${suffix}`, fs.readFileSync(`${path}/${item}`));
//         fs.unlinkSync(`${path}/${item}`);
//     });
//     fs.rmdirSync(path);
//     res.send({
//         code: 0,
//         path: `http://127.0.0.1:${PORT}/upload/${hash}.${suffix}`,
//         fileName: fileName,
//         hash: hash
//     });
// });
app.post('/single3', async (req, res) => {
    let { index } = req.query
    console.log(req.query);

    console.log(index);

    let { fields, files } = await handleMultiparty(req, res, true);
    let [chunk] = files.chunk,
        [filename] = fields.filename;
    let hash = /([0-9a-zA-Z]+)_\d+/.exec(filename)[1],
        path = `${uploadDir}/${hash}`;

    if (!fs.existsSync(path)) fs.mkdirSync(path);
    let chunkPath = `${path}/${filename}`;

    if (fs.existsSync(chunkPath)) {
        return res.send({ code: 0, path: chunkPath.replace(__dirname, `http://127.0.0.1:${PORT}`) });
    }

    let readStream = fs.createReadStream(chunk.path);
    let writeStream = fs.createWriteStream(chunkPath);

    readStream.pipe(writeStream);
    readStream.on('end', () => {
        fs.unlinkSync(chunk.path);
        res.send({ code: 0, path: chunkPath.replace(__dirname, `http://127.0.0.1:${PORT}`) });
    });

    readStream.on('error', (err) => {
        console.error('分片存储失败:', err);
        res.status(500).send({ code: 1, msg: "存储分片失败" });
    });
});

app.get('/merge', (req, res) => {
    let { hash, fileName, totalChunks } = req.query;
    let path = `${uploadDir}/${hash}`,
        fileList = fs.readdirSync(path),
        suffix;

    // **确保所有分片都存在**
    if (fileList.length !== parseInt(totalChunks, 10)) {
        // console.log(totalChunks);
        // console.log('AAA');

        // console.log(fileList.length);

        return res.status(400).send({ code: 1, msg: "分片未上传完整" });
    }

    // **严格数值排序**
    fileList.sort((a, b) => {
        let numA = parseInt(a.split("_").pop());
        let numB = parseInt(b.split("_").pop());
        return numA - numB;
    });

    // **确定文件后缀**
    suffix = /\.([0-9a-zA-Z]+)$/.exec(fileList[0])[1];
    const outputPath = `${uploadDir}/${hash}.${suffix}`;
    const writeStream = fs.createWriteStream(outputPath);

    fileList.forEach((item, index) => {
        const chunkPath = `${path}/${item}`;
        const data = fs.readFileSync(chunkPath);
        writeStream.write(data, () => {
            fs.unlinkSync(chunkPath);
            if (index === fileList.length - 1) {
                writeStream.end();  // 只有最后一个分片写入后再关闭
            }
        });
    });

    writeStream.on("finish", () => {
        fs.rmdirSync(path);
        res.send({
            code: 0,
            path: `http://127.0.0.1:${PORT}/upload/${hash}.${suffix}`,
            fileName: fileName,
            hash: hash
        });
    });

    writeStream.on("error", (err) => {
        console.error("合并失败:", err);
        res.status(500).send({ code: 1, msg: "合并失败" });
    });
});



// app.use(express.static('./'));
// 配置静态文件路径
// app.use('/upload', express.static('upload'));  // 假设上传的文件都保存在 `upload` 文件夹内

app.use((req, res) => {
    res.status(404);
    res.send('NOT FOUND!');
});